<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>雁过留声</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta property="og:type" content="website">
<meta property="og:title" content="雁过留声">
<meta property="og:url" content="http://yanglf007.gitee.io/blog/page/3/index.html">
<meta property="og:site_name" content="雁过留声">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="yanglf007">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/blog/atom.xml" title="雁过留声" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/blog/css/style.css">

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/blog/" id="logo">雁过留声</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/blog/">Home</a>
        
          <a class="main-nav-link" href="/blog/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/blog/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Search"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yanglf007.gitee.io/blog"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main">
  
    <article id="post-rocketmq相关知识" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/08/04/rocketmq%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/" class="article-date">
  <time datetime="2020-08-03T16:42:24.527Z" itemprop="datePublished">2020-08-04</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/08/04/rocketmq%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/">rocketmq相关知识</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">  启动 nameserver</span></span><br><span class="line">nohup sh bin/mqnamesrv &amp;</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 启动 broker</span></span><br><span class="line">nohup sh bin/mqbroker -n localhost:9876 &amp;</span><br><span class="line">nohup sh bin/mqbroker -c ./conf/broker.conf -n localhost:9876 &amp;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 查看所有topic</span></span><br><span class="line"> bin/mqadmin topicList -n localhost:9876</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 手动创建topic</span></span><br><span class="line">   bin/mqadmin updateTopic -n localhost:9876  -b localhost:10911  -t yanlf-TOPIC</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">查看topic状态</span></span><br><span class="line"> bin/mqadmin topicStatus -n localhost:9876 -t yanlf-TOPIC</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">启动生产者测试</span></span><br><span class="line">sh bin/tools.sh org.apache.rocketmq.example.quickstart.Producer</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">启动消费者测试</span></span><br><span class="line">sh bin/tools.sh org.apache.rocketmq.example.quickstart.Consumer</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">工作路径</span></span><br><span class="line">/root/file/rocketmq-all-4.4.0/distribution/target/apache-rocketmq</span><br></pre></td></tr></table></figure>


<p>##问题</p>
<ol>
<li>rocketmq:connect to 172.17.42.1:10911 failed<br>在broker.conf中添加<br>brokerIP1 = 192.168.0.104<br>namesrvAddr = 192.168.0.104:9876<br>启动broker时，带上配置文件<br>nohup sh bin/mqbroker -c ./conf/broker.conf -n localhost:9876 &amp;</li>
</ol>
<p>你对 Namesrv 的了解？<br>保存topic,broker,producer,和consumer的元信息,为producter和consumer提供路由信息</p>
<p>请说说你对 Broker 的了解？<br>接受生产者生成的消息,存储消息,为消费者消费消息做准备</p>
<p>topic<br>信息的分类,生产者更新topic生成消息,消费者根据topic消费消息</p>
<p><a href="https://blog.csdn.net/pzq915981048/article/details/88971356" target="_blank" rel="noopener">https://blog.csdn.net/pzq915981048/article/details/88971356</a></p>
<p>RocketMQ执行流程</p>
<p>1、启动 Namesrv，Namesrv起 来后监听端口，等待 Broker、Producer、Consumer 连上来，相当于一个路由控制中心。</p>
<p>2、Broker 启动，跟所有的 Namesrv 保持长连接，定时发送心跳包。</p>
<p>3、收发消息前，先创建 Topic 。创建 Topic 时，需要指定该 Topic 要存储在 哪些 Broker上。也可以在发送消息时自动创建Topic。</p>
<p>4、Producer 发送消息。</p>
<p>5、Consumer 消费消息。</p>
<p>请说说你对 Producer 的了解？</p>
<p>1、获得 Topic-Broker 的映射关系。</p>
<p>Producer 启动时，也需要指定 Namesrv 的地址，从 Namesrv 集群中选一台建立长连接。</p>
<p>生产者每 30 秒从 Namesrv 获取 Topic 跟 Broker 的映射关系，更新到本地内存中。然后再跟 Topic 涉及的所有 Broker 建立长连接，每隔 30 秒发一次心跳。</p>
<p>2、生产者端的负载均衡。</p>
<p>生产者发送时，会自动轮询当前所有可发送的broker，一条消息发送成功，下次换另外一个broker发送，以达到消息平均落到所有的broker上。</p>
<p>说说你对 Consumer 的了解？</p>
<p>1、获得 Topic-Broker 的映射关系。</p>
<p>Consumer 启动时需要指定 Namesrv 地址，与其中一个 Namesrv 建立长连接。消费者每隔 30 秒从 Namesrv 获取所有Topic 的最新队列情况，</p>
<p>Consumer 跟 Broker 是长连接，会每隔 30 秒发心跳信息到Broker .</p>
<p>2、消费者端的负载均衡。根据消费者的消费模式不同，负载均衡方式也不同。</p>
<p>rocketmq 如何防止消息丢失的</p>
<ol>
<li>放在发送时丢失,通过ack机制,发送到broker时,同步等下返回,返回SEND_OK表示消息发送成功,<br>但是消息发送成功并不代表 消息一定不会丢失,这时候还要开启同步刷盘,同步消息到从节点,只有同步到从节点,才不会发送因为磁盘损坏导致的消息丢失</li>
<li>消费端 只有业务成功才向broker发送 CONSUME_SUCCESS,否则返回RECONSUME_LATER</li>
</ol>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/08/04/rocketmq%E7%9B%B8%E5%85%B3%E7%9F%A5%E8%AF%86/" data-id="ckgtnonn5000mm8ul9xb93g5e" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-自我介绍" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/08/01/%E8%87%AA%E6%88%91%E4%BB%8B%E7%BB%8D/" class="article-date">
  <time datetime="2020-08-01T07:41:47.277Z" itemprop="datePublished">2020-08-01</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/08/01/%E8%87%AA%E6%88%91%E4%BB%8B%E7%BB%8D/">自我介绍</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>问面试官问题<br>需要补充哪些技术栈，哪些方面需要提高</p>
<pre><code>Good morning !
It is really my honor to have this opportunity for a interview,I hope i can make a good
performance today. I&apos;m confident that I can succeed.
Now i will introduce myself briefly I am 23 years old,born in shenzhen.
I was graduated from shenzhen university. my major is electronic.and i will got my
bachelor degree after my graduation in the year of 2008.
I spend most of my time on study,i have passed CET4/6。and i have acquired basic
knowledge of my major during my school time.
In July 2007, I begin work for a small private company as a technical support engineer in
shenzhen city.Because I&apos;m capable of more responsibilities, so I decided to change my
job.
And in August 2004,1 left QingDao to BeiJing and worked for a foreign enterprise as a
automation software test engineer Because I want to change my working environment, I&apos;d
like to find a job which is more challenging. Morover Motorola is a global company, so I
feel | can gain the most from working in this kind of company ennvironment. That is the
reason why I come here to compete for this position.
I think I&apos;m a good team player and I&apos;m a person of great honesty to others. Also I am able
to work under great pressure.That&apos;s all. Thank you for giving me the chance.




General Introduction
| am a third year master major in automation at Shanghai Jiao
Tong University; P. R. China. With tremendous interest in Industrial Engineering, I am
writing to apply for acceptance
into your Ph.D. graduate program.
Education background In 1995, I entered the Nanjing University of Science &amp; Technology
(NUST) --widely considered one of the China&apos;s best engineering schools. During the
following undergraduate study, my academic records kept distinguished among the
whole department. I was granted First Class Prize every semester,In 1999, I got the
privilege to enter the graduate program
waived of the admission test.
At the period of my graduate study, my overall GPA(3.77/4.0) ranked top 5% in the
department In the second semester, I became teacher assistant that is given to talented
and matured students only. This year, I won the Acer Scholarship
as the one and only candidate in my department, which is the ultimate accolade for
distinguished students endowed by my
university. Presently, | am preparing my graduation thesis and trying for the honor of
Excellent Graduation Thesis.
Research experience and academic activity When a sophomore, I joined the Association
of Al Enthusiast
and began to narrow down my interest for my future research.
With the tool of OpenGL and Mattab, I designed a simulation program for transportation
scheduling system. It is now widely used by different research groups in NUST. |
assumed and fuflled a sewage analysis &amp; dispose project for Nanjing sewage treatment
plant. This was my first practice to convert a laboratory idea to a commercial product.
In retrospect, I find myself standing on a solid basis in both theory and experience, which
has prepared me for the Ph.D. program. My future research interests include: Network
Scheduling Problem, Heuristic Algorithm research (especially in GA and Neural network),
Supply chain network research, Hybrid system performance analysis with Petri nets and
Data
Mining.
Data
Mining.
1、Good morning/afternoon/evening, my name is。It is really a great honor to have this
opportunity/chance to introduce myself.I would like to answer whatever you may raise,
and I hope I can make a good performance today.</code></pre>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/08/01/%E8%87%AA%E6%88%91%E4%BB%8B%E7%BB%8D/" data-id="ckgtnonnb000vm8ulerj1dqli" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-面试全集" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/" class="article-date">
  <time datetime="2020-08-01T06:43:37.632Z" itemprop="datePublished">2020-08-01</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/">面试全集</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h3 id="集合"><a href="#集合" class="headerlink" title="集合"></a>集合</h3><ol>
<li>java 有哪些常用容器，哪些是同步容器，哪些是并发容器<br>答案: ArrayList,LinkedList,HashMap,hashSet,treeSet;<br>CopyOnWriteArrayList,HashTable,ConcurrentHashMap,</li>
<li>ArrayList 插入和 LinkedList 插入时间复杂度<pre><code>插入    查找    删除</code></pre>arrayList       o(1)    o(1)<br>linkedList      o(1)    o(n)</li>
</ol>
<ol start="3">
<li>hashMap 什么情况下回扩容，或者哪些操作会扩容</li>
</ol>
<p>HashMap 默认大小16，加载因子0.75 ，每次扩容2，为2的原因是 hash%length==hash&amp;(length-1)的前提是length是2的n次方<br>4. hashMap put方法执行过程<br>第一步. 进来先检查 数组是否为空，为空的话先创建一个大小为16的数组<br>第二步. 取key的hash值与数组仓库取余得到坐标i，看i所在位置是否为空，如果为空，直接构建一个node<br>第三步. 检查i所在为啥是否是树节点，如果不是树节点，那就是链表，循环遍历链表，插入到最后一个节点，检查链表长度是否达到数的阈值8，（小于6退化成链表）<br>        达到了就进行树化，在树化的时候继续检查，如果table的长度小于64，直接进行扩容，不需要树化，否则  链表转换为一棵红黑树，<br>        如果是treenode节点</p>
<ol start="5">
<li><p>hashMap检测到hash冲突，插入链表的末尾还是开头<br>Node 结构 泛型类型key 和 value, final 修饰的 int 类型 的 hash ,next下一个node节点<br>TreeNode 结构 左节点，右节点，父节点，前节点，后节点（继承来的）<br>插入链表末尾，node 是一个单向链表</p>
<p>1.7插入元素到单链表中采用头插入法，1.8采用的是尾插入法。<br>HashMap在jdk1.7中采用头插入法，在扩容时会改变链表中元素原本的顺序，以至于在并发场景下导致链表成环的问题。而在jdk1.8中采用尾插入法，在扩容时会保持链表元素原本的顺序，就不会出现链表成环的问题了。</p>
</li>
</ol>
<ol start="6">
<li>1.8红黑树，红黑树特点，为什么用红黑树，不用avl树和 b树<br>avl树（平衡二叉树） 插入慢，查询快，<br>红黑树特点：<br>一个节点必须是红色或者黑色<br>根节点必须是黑色<br>如果一个节点是红色，则子节点必须是黑色<br>一个节点到空引用的节点必须包含相同数量的黑色节点，红色节点不受影响<br>插入点默认为红色<br>困难点：插入一个项是要维持树的高度，需要进行树的变形    </li>
</ol>
<p>左旋， 大儿子变父亲，小孙子变儿子<br>左旋旋转点为父亲节点，右旋旋转点为爷爷</p>
<pre><code>旋转和颜色变换规则:所有插入的点默认为红色&quot;,
1.变颜色的情况:当前结点的父亲是红色，且它的祖父结点的另一个 子结点&quot;,
也是红色。( 叔叔结点) :&quot;,
(1)把父节点设为黑色&quot;,
( 2 )把叔叔也设为黑色&quot;,
( 3 )把祖父也就是父亲的父亲设为红色(爷爷)&quot;,
( 4 )把指针定义到祖父结点设为当前要操作的.(爷爷)分析的点变换的规则&quot;,
2.左旋:当前父结点是红色，叔叔是黑色的时候,且当前的结点是右子树。左旋&quot;,
以父结点作为左旋。&quot;,
3.右旋:当前父结点是红色，叔叔是黑色的时候,且当前的结点是左子树。右旋&quot;,
(1)把父结点变为黑色&quot;,
I&quot;,
(2)把祖父结点变为红色(爷爷)&quot;,
( 3 )以祖父结点旋转(爷爷) TreeMap JDK1.8大学给小学弟( )&quot;,</code></pre><ol start="7">
<li>ConcurrentHashMap </li>
</ol>
<p>ConcurrentHashMap 初始化，调用put的时候进行初始化，先检查map是否为空，如果为空检查 进入一个while循环，检查sizeCtl大小,如果sizeCtl&lt;0<br> 表示有线程正在初始化table,调用thread.yield()让出线程，如果&gt;=0， 通过cas操作，将sizeCtl 设置为-1，然后进行初始化，扩容阈值设置table长度的0.75</p>
<p>tableAt(),casTableAt() setTableAt() 三个原子操作</p>
<p>锁是通过synchronized 锁住hash桶中的头结点，相比Segment优势是，锁的颗粒度小，并且由jvm进行管理锁升级过程，无锁，偏向锁，轻量级锁，重量级锁</p>
<p>put过程：<br>1 检查key 和 value 是否为空<br>2 spread（）方法转换hash值，全部转为大于0的值，<br>3 启动一个无限循环，判断table是否为空，为空进行table初始化<br>4 调用tabAt原子操作查看 需要放入的槽位置是否为空，如果为空，调用casTabAt 进行设置<br>5 如果不为空，检查hash值是否等于-1 （MOVE）,-1表示是一个ForwardingNode，是一个临时节点，在扩容时才会出现，不存储数据，如果就的hash桶<br>中数据已经移到新的hash桶中，就放一个ForwardingNode，指向新的table数组，遇到读的时候在新table中查找，遇到写的时候帮忙扩容<br>如果 hash大于0，使用synchronized 对头部结点进行加锁，然后再判断是链表还是TreeBin,来添加到链表后面，还是加在红黑树树，</p>
<p>get过程<br>1 spread（）转换hash值，调用tableAt()获取结点，如果为空，返回空，<br>不为空时，判断当前结点是否是要取得值（hash相等，并行key相等），如果是返回<br>如果当前hash值小于0，当为-1时，表示hash槽进行扩容，调用ForwardingNode 的find方法，找到新的table,在新table中寻找<br>当为-2时表示是一个treein,调用treeBin 的find方法进行查找<br>否则表示是一个链表，循环遍历，判断key是否相同就行</p>
<p>并发扩容过程<br><a href="https://blog.csdn.net/ZOKEKAI/article/details/90051567" target="_blank" rel="noopener">https://blog.csdn.net/ZOKEKAI/article/details/90051567</a><br>putval()调用完成的最后调用addCount() 方法<br>利用 CounterCell 做了一个分段设计，就是通过一次cas更新不成功的话，计算当前线程所在的位置，更新这个位置的值，通过for循环和cas更新<br>CounterCell 被@sun.misc.Contended 修饰，防止伪共享<br>加起来sum就是所有元素的个数，如果大于 sizeCtl（数组长度*加载因子），<br>如果当前的数据sizeCtl 小于0，表示有线程在进行扩充<br>最终调用 transfer() 进行扩容<br>每个线程扩容的桶数与cpu核心数有关，核心越多，单个线程处理桶数越少，每个线程最少分配16个桶<br>新建一个node节点的数组，大小是当前table的两倍，作为nextTable</p>
<p>size()<br>size是由sumCount方法决定，技术counterCell 数组之和</p>
<ol start="8">
<li><p>hashMap怎么解决hash冲突</p>
</li>
<li><p>arrayList 扩容<br>答： 每次增加元素时会检查数组容量，<br>首先需要的大小和默认大小10 比较取大的，<br>如果需要的最小长度，大于当前数组长度，进行数组扩容<br>需要的最小长度 和 数组长度的1.5倍比较，如果最小值比1.5倍大，扩容的大小就是最小长度， 或者就是数组的1.5倍扩容<br>此外，还会坚持是否大于默认最大值，Integer.MAX_VALUE - 8 （原因是一些虚拟机会保存数组的头信息）, 如果大于，扩容大小改为Integer.MAX_VALUE</p>
</li>
</ol>
<p>10 queue 和 deque 区别<br>queue 是 deque的接口，是一个先进先出队列 实现有 DelayQueue，<br>deque 是一个双向队列，实现由LinkedList</p>
<p>11 Collections.synchronizedHashMap(new HashMap()) 如何实现线程安全<br>返回的是 SynchronizedMap ，在调用构造方法的时候，把当前对象作为互斥量，调用插入，查询是，synchronized 对当前对象加锁，同一个线程的当前对象才能访问</p>
<ol start="12">
<li>StringBuffer 和StringBuilder<br>StringBuffer是线程安全的，所有公开方法加synchronized，所以性能不好，</li>
</ol>
<h3 id="io"><a href="#io" class="headerlink" title="io"></a>io</h3><h3 id="java-并发类-juc"><a href="#java-并发类-juc" class="headerlink" title="java 并发类 juc"></a>java 并发类 juc</h3><ol>
<li><p>讲一讲 AtomicInteger，为什么用cas,而不是 syschronized ,AtomicReference</p>
</li>
<li><p>java锁有哪些类，以及区别</p>
</li>
<li><p>LongAddr原理<br>内部维护了一个cell 数组，通过cas去更新值，如果更新成功推出，否则多个线程只有一个成功，其他失败，失败的找到当前线程在cell 中的坐标，通过循环 和cas<br>更新坐标的值，最后调用sum方法是计算各个桶数据之和<br><a href="https://blog.csdn.net/wolf_love666/article/details/87693771" target="_blank" rel="noopener">https://blog.csdn.net/wolf_love666/article/details/87693771</a></p>
</li>
<li><p>LongAdder如何解决缓存行问题<br>一个缓存行一般大小64字节,long类型8个字节，更新当前值导致其他值失效，同样需要从主内存加载，称之为伪共享<br>早期是定义几个无用变量放在一起，<br>之和可以通过sun.mis.contended注解解决</p>
</li>
</ol>
<ol start="6">
<li>可重入锁reentrantLock实现原理<br>调用tryAcquire 的时候会检查 state是否等于0 ,如果不等于0 ,判断当前独占线程是否等于当前线程,如果等于就在状态上加一</li>
</ol>
<p>加锁过程 reentrantLock 默认非公平锁 </p>
<p>0)调用lock,一次cas修改状态,失败后调用acquire()<br>acquire()加锁过程分三步:<br>1)tryAcquire()<br>如果状态是0,通过一次cas修改状态,如果修改成功,将独占线程设置为当前线程<br>2)addWaiter()<br>获取锁没有成功的时间就加入等待队列,node节点链表,加入末尾<br>enq；通过cas将当前结点设置为尾结点<br>3)acquireQueued()<br>如果当前节点的前一个节点是head节点,再次tryAcquire,试图获取锁<br>调用parkAndCheckInterrupt来达到阻塞效果 </p>
<p>公平锁和非公平锁的主要区别在于：<br>非公平锁上来就cas修改状态，如果是0，就可以修改成功获取锁<br>公平锁，如果是0 ，会判断是否有前驱结点，如果有，就老老实实排队</p>
<p>去锁过程</p>
<p>1) 状态减一,如果状态为0,将独占线程置为空<br>2) 如果状态为0,调用unparkSuccessor(),唤醒头节点的下一节点LockSupport.unpark(s.thread);</p>
<h3 id="多线程"><a href="#多线程" class="headerlink" title="多线程"></a>多线程</h3><ol>
<li><p>线程池工作原理，几个重要参数作用，阻塞队列作用</p>
</li>
<li><p>说一下对Synchronized 和lock的理解，说说他们之间区别<br>要点：乐观悲观，锁升级过程，静态代码块，同步代码块区别， lock的几个实现，实现原理 aqs</p>
</li>
</ol>
<p>AbstractQueuedSynchronizer 类如其名，抽象的队列式的同步器，AQS 定义了一套多线程访问<br>共享资源的同步器框架，许多同步类实现都依赖于它，如常用的<br>ReentrantLock/Semaphore/CountDownLatch</p>
<p>synchronized 底层依赖操作系统 Mutex Lock实现，是一个可重入锁<br>操作系统实现线程直接切换，需要从用户态转换到核心态，成本高<br><img src="http://chuantu.xyz/t6/740/1596546954x1033347913.jpg" alt="avator"></p>
<p>锁粗化：将很多次锁的请求合并成一次，以降低短时间内大量锁请求，释放带来的性能损耗</p>
<figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for(int i=0;i&lt;size;i++)&#123;</span><br><span class="line">    synchronized(lock)&#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>锁消除 编译器级别的事情，编译器发现如果不可能被共享的对象，可以消除这些对象的锁操作</p>
<p>synchronized 锁升级过程</p>
<p>只有一个线程的情况</p>
<p>1,检查锁标识位,markword最后两位 01 ,标识无锁和偏向锁<br>前一位 如果是0 ,表示无锁,将无锁升级成偏向锁,cas操作,将对象头中的hashCode换成当前线程ID<br>第二次进入的时候检查是否是偏向锁,如果是偏向锁,检查对象头的线程ID是否是当前ID,如果是当前ID,则获得锁</p>
<p>有多个线程<br>A线程拿到偏向锁, 线程B无锁状态,<br>线程B到达synchronized代码块,将无锁升级成偏向锁,cas替换对象头中的hashCode为当前线程ID,成功则获取对象锁<br>失败:开始出现锁竞争,撤销偏向锁,到达安全点,暂停执行原偏向锁线程<br>A开始升级成轻量级锁,向线程栈中分配锁记录,copy对象头中markword 到锁记录中,对象头中保存锁记录指针,锁标志位变为00,唤醒A线程,从安全点开始执行,开始轻量级锁解锁<br>B线程锁升级位轻量级锁,在当前线程栈中分配锁记录,将对象头markword copy到线程锁记录中,cas参数修改对象头锁记录指针,指向当前线程锁记录<br>失败就进行自旋,达到一定次所后升级成重量级说,锁标识位改为10,进入互斥量(mutex)队列挂起等待</p>
<p>轻量级解锁:cas操作,对比对象头中markword中锁指针是否是当前线程,当前线程的锁记录是否和对象头中markword一致, 成功则获取锁,失败升级成重量级锁进行等待</p>
<p>vilitate 关键字</p>
<p>内存屏障<br> (1）在每一个volatile写操作前面插入一个StoreStore屏障。这确保了在进行volatile写之前前面的所有普通的写操作都已经刷新到了内存。<br>（2）在每一个volatile写操作后面插入一个StoreLoad屏障。这样可以避免volatile写操作与后面可能存在的volatile读写操作发生重排序。<br>（3）在每一个volatile读操作后面插入一个LoadLoad屏障。这样可以避免volatile读操作和后面普通的读操作进行重排序。<br>（4）在每一个volatile读操作后面插入一个LoadStore屏障。这样可以避免volatile读操作和后面普通的写操作进行重排序。</p>
<p>写操作前,在前后增加屏障<br>读操作后,在后面加两个屏障</p>
<ol start="3">
<li><p>如何保证线程安全</p>
</li>
<li><p>线程池创建和运行过程</p>
</li>
<li><p>threadLocal</p>
</li>
<li><p>同步，异步，并发，并行区别</p>
</li>
</ol>
<p>并发只具有处理多个任务的能力，不一定同时进行<br>并行是同时处理多个任务的能力</p>
<ol start="8">
<li>thread 方法<br>Thread.yield()；当前线程由执行状态变成就绪状态，让出cpu时间，在下一个程序执行时，当前线程可能被执行，也可能不被执行<br>Thread.currentThread()；获取当前线程<br>sleep(); 休眠一段时间，不会让出锁；<br>start();线程启动入口，会将当前线程加入threadGroup中，调用native　start0 方法启动一个线程<br>run();实现runable 接口，必须实现run方法，直接调用相当于调用普通方法<br>stop(); 以过期，线程不安全 UnsupportedOperationException</li>
</ol>
<p>interrupt() 给调用的线程设置一个中断标识位,遇到sleep,wait会中断,报InterruptedException异常<br>interrupted() 重置中断标识位,被中断后重置,不会抛出异常<br>isInterrupted() 判断线程的中断标识位<br>join() 阻塞执行代码的线程,等待join的调用线程执行完成,内部实现是object.wait(),线程执行完成会有一个notify_all</p>
<ol start="9">
<li><p>thread的start方法能调用两次吗<br>不能，第二次报java.lang.IllegalThreadStateException，启动时会检查状态是否为0<br>start是一个同步方法，启动线程时会将当前线程加入到ThreadGroup中，调用native start0方法</p>
</li>
<li><p>thread 状态有哪些<br>NEW 新建<br>RUNNABLE 可以运行<br>BLOCKED 阻塞 线程调用object.wait thread.join LockSupport.park 的时候变成 WAITING<br>WAITING<br>TIMED_WAITING<br>TERMINATED</p>
</li>
</ol>
<p><img src="https://images.gitee.com/uploads/images/2020/0810/113838_acbcc8db_1207148.jpeg" alt="avator"></p>
<ol start="11">
<li><p>object 方法<br>wait(); 当前线程休眠，让出对象锁，让其他持有当前对象的锁开始执行，直到有人唤醒,唤醒后需要重新获取锁<br>notify();唤醒其他休眠线程,不会让出cpu，会继续执行，被唤醒的线程需要重新获取锁</p>
</li>
<li><p>LockSupport.park</p>
<p>线程池 execute执行逻辑</p>
<pre><code>1,检查执行命令是否为空,为空报空指针异常
2,如果当前工作线程数,小于核心线程数,开启一个工作线程执行当前命令
3,如果线程池状态是运行状态,开始向队列中添加命令
    如果添加失败,不能进入队列,尝试开启一个新线程,开启失败时报拒绝服务
4,如果添加成功,进行双重校验,如果当前线程池状态不是运行中,则从队列中移出命令,报拒绝服务

添加工作线程的逻辑
1,检查如果不是运行中
2,开启一个循环 如果工作线程数大于 最大核心线程数,或者线程池最大线程数 直接返回false,添加线程失败
3,通过cas更新工作线程数,更新成功退出循环,更新失败,继续重新    cas更新
4,创建一个Worker,将当前命令commond作为构造方法的参数传递进去,并且从线程工厂拿到一个新线程 (ThreadFactory) ,默认是 Executors.defaultThreadFactory()
5,从worker中拿到线程,如果线程不为空,ReentrantLock 加锁 ,将worker加入到hashset的线程队列中,然后释放锁
6,如果添加线程成功,调用start方法执行线程,因为worker试下了runnble接口,实际上是开启线程执行run方法,实际就是执行 runWorker方法
7,后面看不懂了 java.util.concurrent.ThreadPoolExecutor#runWorker

execute 和 submit 区别
submit 提交线程的时候会返回一个Future对象,内部执行的还是execute方法

创建线程的构造方法
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler(AbortPolicy)</span><br></pre></td></tr></table></figure></code></pre></li>
</ol>
<pre><code>DefaultThreadFactory 工厂模式

  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> Thread <span class="title">newThread</span><span class="params">(Runnable r)</span> </span>&#123;</span><br><span class="line">      Thread t = <span class="keyword">new</span> Thread(group, r,namePrefix + threadNumber.getAndIncrement(),<span class="number">0</span>);</span><br><span class="line">      <span class="keyword">if</span> (t.isDaemon())</span><br><span class="line">          t.setDaemon(<span class="keyword">false</span>);</span><br><span class="line">      <span class="keyword">if</span> (t.getPriority() != Thread.NORM_PRIORITY)</span><br><span class="line">          t.setPriority(Thread.NORM_PRIORITY);</span><br><span class="line">      <span class="keyword">return</span> t;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure></code></pre><p>  FutureTask原理</p>
<pre><code>private static final int NEW          = 0;
private static final int COMPLETING   = 1;
private static final int NORMAL       = 2;
private static final int EXCEPTIONAL  = 3;
private static final int CANCELLED    = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED  = 6;</code></pre><p>设置结果前通过cas设置为COMPLETING<br>设置结果后通过cas设置为NORMAL</p>
<p>LockSupport.unpark(t);</p>
<p>FutureTask调用 get()方法的时候，如果状态小于COMPLETING,调用awaitDone()方法，</p>
<p>awaitDone()中判断是否有等待时间，结束时间就是当前时间加等待时间<br>进入循环体，如果超时，从等待队列中移除，返回当前状态<br>如果状态是COMPLETING，就调用 Thread.yield(),休眠，让出当前cpu,<br>如果状态COMPLETING，就是NORMAL，就结束循环返回状态</p>
<p>调用report(),返回数据，如果状态是NORMAL，正常返回，否则抛出异常</p>
<p>13 创建线程池方法<br>Executors.newScheduledThreadPool() 每隔多少时间执行一次，<br>scheduleAtFixedRate 两次开始间隔时间<br>scheduleWithFixedDelay 第一次执行完，到第二次执行时间<br>Executors.newFixedThreadPool(1);<br>Executors.newSingleThreadExecutor(); 发送异常后重启一个线程来执行原任务<br>Executors.newCachedThreadPool();</p>
<ol start="14">
<li>线程状态<br>new<br>Runnable<br>Running运行中<br>Blocked 阻塞 synchronized会导致线程进入block状态<br>WAITING 等待 Object.wait会导致线程进入wait状态<br>TIMED_WAITING Thread.sleep(0)<br>TERMINATED 终止</li>
</ol>
<ol start="15">
<li><p>线程异常退出源码分析<br><a href="https://www.cnblogs.com/wang-meng/p/10588637.html" target="_blank" rel="noopener">https://www.cnblogs.com/wang-meng/p/10588637.html</a></p>
<h3 id="反射"><a href="#反射" class="headerlink" title="反射"></a>反射</h3></li>
<li><p>java反射原理，注解原理</p>
</li>
<li><p>反射的作用是什么</p>
</li>
<li><p>Thread方法有哪些<br>Thread.sleep(0)<br>Thread.join<br>thread.notify()<br>thread.notifyAll()<br>thread.currentThread()<br>thread.isAlive()<br>thread.isDaemon()<br>thread.setDaemon()<br>thread.setPriority()<br>thread.getPriority()</p>
</li>
<li><p>死锁产生的条件<br>互斥条件：进程要求对所分配的资源进行排它性控制，即在一段时间内某资源仅为一进程所占用。<br>请求和保持条件：当进程因请求资源而阻塞时，对已获得的资源保持不放。<br>不剥夺条件：进程已获得的资源在未使用完之前，不能剥夺，只能在使用完时由自己释放。<br>环路等待条件：在发生死锁时，必然存在一个进程–资源的环形链。</p>
</li>
</ol>
<p>解决死锁：</p>
<ol>
<li>一次性获取所有资源</li>
<li>获取部分资源，等不到其他资源，则释放掉已经得到的资源</li>
<li>资源有序分配</li>
</ol>
<p>18 线程池原理</p>
<p>线程池做的工作主要是控制运行的线程的数量，处理过程中将任务放入队列，然后在线程创建后<br>启动这些任务，如果线程数量超过了最大数量超出数量的线程排队等候，等其它线程执行完毕，<br>再从队列中取出任务来执行。他的主要特点为：线程复用；控制最大并发数；管理线程</p>
<ol start="19">
<li>线程池状态<br>private static final int RUNNING    = -1 &lt;&lt; COUNT_BITS;<br>private static final int SHUTDOWN   =  0 &lt;&lt; COUNT_BITS;<br>private static final int STOP       =  1 &lt;&lt; COUNT_BITS;<br>private static final int TIDYING    =  2 &lt;&lt; COUNT_BITS;<br>private static final int TERMINATED =  3 &lt;&lt; COUNT_BITS;</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">execute</span><span class="params">(Runnable command)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (command == <span class="keyword">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">       </span><br><span class="line">        <span class="keyword">int</span> c = ctl.get();</span><br><span class="line"><span class="comment">//当前工作线程小于核心线程</span></span><br><span class="line">        <span class="keyword">if</span> (workerCountOf(c) &lt; corePoolSize) &#123;</span><br><span class="line">            <span class="keyword">if</span> (addWorker(command, <span class="keyword">true</span>))</span><br><span class="line">                <span class="keyword">return</span>;</span><br><span class="line">            c = ctl.get();</span><br><span class="line">        &#125;</span><br><span class="line"><span class="comment">//正在运行时，工作队列中添加命令</span></span><br><span class="line">        <span class="keyword">if</span> (isRunning(c) &amp;&amp; workQueue.offer(command)) &#123;</span><br><span class="line">            <span class="keyword">int</span> recheck = ctl.get();</span><br><span class="line">            <span class="keyword">if</span> (! isRunning(recheck) &amp;&amp; remove(command))</span><br><span class="line">                reject(command);</span><br><span class="line"><span class="comment">//当前工作线程数为0</span></span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span> (workerCountOf(recheck) == <span class="number">0</span>)</span><br><span class="line">                addWorker(<span class="keyword">null</span>, <span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"><span class="comment">//开启一个非核心线程</span></span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (!addWorker(command, <span class="keyword">false</span>))</span><br><span class="line">            reject(command);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<p>线程池原理<br><img src="https://images.gitee.com/uploads/images/2020/0810/113838_92aea2f6_1207148.jpeg" alt="avator"><br>核心线程 ：固定线程数 可闲置 不会被销毁 ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true时，keepAliveTime同样会作用于核心线程<br>非核心线程数：非核心线程闲置时的超时时长，超过这个时长，非核心线程就会被回收</p>
<p>20 阻塞队列原理<br>不能插入空值</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">put</span><span class="params">(E e)</span> <span class="keyword">throws</span> InterruptedException </span>&#123;</span><br><span class="line">       <span class="keyword">if</span> (e == <span class="keyword">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> NullPointerException();</span><br><span class="line">       <span class="keyword">int</span> c = -<span class="number">1</span>;</span><br><span class="line">       Node&lt;E&gt; node = <span class="keyword">new</span> Node&lt;E&gt;(e);</span><br><span class="line">       <span class="keyword">final</span> ReentrantLock putLock = <span class="keyword">this</span>.putLock;</span><br><span class="line">       <span class="keyword">final</span> AtomicInteger count = <span class="keyword">this</span>.count;</span><br><span class="line">       putLock.lockInterruptibly();</span><br><span class="line">       <span class="keyword">try</span> &#123;</span><br><span class="line">           <span class="keyword">while</span> (count.get() == capacity) &#123;</span><br><span class="line">               notFull.await();</span><br><span class="line">           &#125;</span><br><span class="line">           enqueue(node);</span><br><span class="line">           c = count.getAndIncrement();</span><br><span class="line">           <span class="keyword">if</span> (c + <span class="number">1</span> &lt; capacity)</span><br><span class="line">               notFull.signal();</span><br><span class="line">       &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">           putLock.unlock();</span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">if</span> (c == <span class="number">0</span>)</span><br><span class="line">           signalNotEmpty();</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<p>add offer put 区别<br>remove poll,take<br>没有添加成功，抛异常，offer没有添加成功返回false,put会阻塞<br>满的队列未满时用 notFull条件锁唤醒</p>
<p>空的队列未空时 notEmpty条件锁唤醒</p>
<ol start="21">
<li>condition锁方法<br>await<br>await<br>awaitNanos<br>awaitUninterruptibly<br>awaitUntil<br>signal<br>signalAll</li>
</ol>
<h4 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h4><h4 id="类加载机制"><a href="#类加载机制" class="headerlink" title="类加载机制"></a>类加载机制</h4><p>加载 读取class文件，在内存中生成一个类的class对象<br>验证 确保class文件的字节流符合虚拟机要求<br>准备 为类变量分配内存空间，初始值为0，<br>解析 将常量池中的符号引用替换成直接引用<br>初始化 开始执行java代码，<br>使用<br>卸载</p>
<h4 id="双亲委派模型"><a href="#双亲委派模型" class="headerlink" title="双亲委派模型"></a>双亲委派模型</h4><p>当一个类收到加载请求，首先不会直接加载这个类，而是委派给父类去完成，如果父类不能加载，子类加载器才会尝试加载</p>
<p>BootstrapClassLoader  java_home/jre/lib<br>ExtClassLoader java_home/jre/lib/ext<br>AppClassLoader 应用程序类加载器 加载classpath<br> 用户自定义的类</p>
<h4 id="如何打破双亲委派"><a href="#如何打破双亲委派" class="headerlink" title="如何打破双亲委派"></a>如何打破双亲委派</h4><h4 id="为什么用双亲委派"><a href="#为什么用双亲委派" class="headerlink" title="为什么用双亲委派"></a>为什么用双亲委派</h4><h4 id="jvm内存模型"><a href="#jvm内存模型" class="headerlink" title="jvm内存模型"></a>jvm内存模型</h4><h4 id="类实例化顺序"><a href="#类实例化顺序" class="headerlink" title="类实例化顺序"></a>类实例化顺序</h4><h3 id="框架"><a href="#框架" class="headerlink" title="框架"></a>框架</h3><h4 id="spring"><a href="#spring" class="headerlink" title="spring"></a>spring</h4><ol>
<li><p>springmvc 处理全流程</p>
</li>
<li><p>spring 容器初始化过程，ioc加载过程(<strong>重要</strong>）</p>
</li>
<li><p>spring 单例bean注入过程</p>
</li>
<li><p>spring bean循环依赖</p>
</li>
<li><p>spring中事物的隔离级别</p>
</li>
</ol>
<h4 id="dubbo"><a href="#dubbo" class="headerlink" title="dubbo"></a>dubbo</h4><ol>
<li>dubbo中rpc如何实现</li>
<li>自己实现rpc，应该怎么做</li>
<li>dubbo 的服务注册和发现</li>
</ol>
<h4 id="netty"><a href="#netty" class="headerlink" title="netty"></a>netty</h4><ol>
<li>netty优点，原理</li>
</ol>
<h4 id="mybatis"><a href="#mybatis" class="headerlink" title="mybatis"></a>mybatis</h4><ol>
<li><p>mybatis #和$ 的区别</p>
</li>
<li><p>mybatis dao和xml怎么建立关系</p>
</li>
</ol>
<h3 id="mysql"><a href="#mysql" class="headerlink" title="mysql"></a>mysql</h3><ol>
<li><p>什么情况下导致不会使用索引</p>
</li>
<li><p>数据库索引，底层怎么实现，为什么要用b树索引,b+树大致结构</p>
</li>
<li><p>谈一谈数据库乐观锁和悲观锁</p>
</li>
<li><p>mysql 隔离级别</p>
</li>
<li><p>可以重复读实现原理（mvcc机制） 多版本并发控制</p>
</li>
<li><p>mysql用什么存储引擎，存储引擎用的什么数据结构，有哪些优缺点，怎么使用<br>b+树，为什么不用b树，不能范围查询，阶是根据缓存也大小16k和单个索引大小共同确定的， b树分裂，中间值拿到父节点，b+树分裂，最大值存到父节点，</p>
</li>
<li><p>mysql有哪些锁<br>一、按照对数据操作的锁粒度来分：行级锁、表级锁、页级锁、间隙锁</p>
</li>
</ol>
<p>1 行级锁</p>
<p>2 表级锁</p>
<p>3 页级锁</p>
<p>二、按照锁的共享策略来分：共享锁、排他锁、意向共享锁、意向排他锁<br>innodb的意向锁有什么作用？<br>三、从锁策略上分：乐观锁和悲观锁<br>四、其他：自增锁<br>自增锁（AUTO-INC锁）</p>
<ol start="8">
<li>分库分表<br><a href="https://blog.csdn.net/qq_39416311/article/details/86730483" target="_blank" rel="noopener">https://blog.csdn.net/qq_39416311/article/details/86730483</a><br>分库分表带来的问题:<br>主键还是自增,生成一个业务组件code,<br>code有业务域和ID组成,这个ID通过redis自增实现的(Incr),</li>
</ol>
<p>其他方案,<br>雪花算法,第一位符合位 ,41位时间截,10 机器序号,12位序列,没毫秒可以产生4096个ID<br>根据步长设置自增</p>
<h3 id="redis"><a href="#redis" class="headerlink" title="redis"></a>redis</h3><ol>
<li><p>MongoDB 和 redis适用哪些场景</p>
</li>
<li><p>分布式事物TCC服务设计</p>
</li>
<li><p>redis 和 memcache 有什么区别，redis为什么相比memcache有优势</p>
</li>
<li><p>谈谈分布式锁，以及分布式全局唯一ID的实现和比较</p>
</li>
<li><p>redis 怎么实现分布式锁</p>
</li>
<li><p>redis 数据结构</p>
</li>
<li><p>缓存穿透，缓存雪崩，缓存击穿</p>
</li>
<li><p>redis 为什么那么快<br>单线程，内存，io多路复用（深入）</p>
</li>
<li><p>缓存的实现原理，设计缓存要注意什么</p>
<p>  缓存是在内存或数据库中间存储的一道门槛，为了查询快速，要注意数据一致性<br> 1）缓存和db同时更新数据，不在同一个事物，且没有补偿机制<br> 2）没有查到缓存导致数据库被打爆</p>
</li>
</ol>
<ol start="10">
<li><p>redis服务器怎么扩容</p>
</li>
<li><p>redis失效key清除策略</p>
</li>
<li><p>redis怎么实现附件的人 （空间索引）</p>
</li>
<li><p>热点数据失效问题</p>
</li>
<li><p>先删除缓存，还是先更新数据库</p>
</li>
<li><p>redis cluster 如何试下高可用<br>集群是一个由多个主从节点群组成的分布式服务器群，它具有复制、高可用和分片特性。Redis cluster集群不需要sentinel哨兵也能完成节点移除和故障转移的功能<br>集群模式<br>redis cluster集群需要至少要三个master节点，这里搭建三个master节点，并且给每个master再搭建一个slave节点，总共6个redis节点，</p>
</li>
</ol>
<p>哨兵模式是一种特殊的模式，首先Redis提供了哨兵的命令，哨兵是一个独立的进程，作为进程，它会独立运行。其原理是哨兵通过发送命令，等待Redis服务器响应，从而监控运行的多个Redis实例<br>通过发送命令，让Redis服务器返回监控其运行状态，包括主服务器和从服务器。<br>当哨兵监测到master宕机，会自动将slave切换成master，然后通过发布订阅模式通知其他的从服务器，修改配置文件，让它们切换主机。<br>然而一个哨兵进程对Redis服务器进行监控，可能会出现问题，为此，我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控，这样就形成了多哨兵模式。<br>用文字描述一下故障切换（failover）的过程。假设主服务器宕机，哨兵1先检测到这个结果，系统并不会马上进行failover过程，仅仅是哨兵1主观的认为主服务器不可用，这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用，并且数量达到一定值时，那么哨兵之间就会进行一次投票，投票的结果由一个哨兵发起，进行failover操作。切换成功后，就会通过发布订阅模式，让各个哨兵把自己监控的从服务器实现切换主机，这个过程称为客观下线。这样对于客户端而言，一切都是透明的。</p>
<ol start="16">
<li><p>说说redis的持久化机制，为啥不能用redis做专门的持久化数据库存储<br>1) 容量限制<br>2) 数据容易丢失<br>3) 数据解构基于key-value,无法关联查询</p>
<h3 id="消息队列"><a href="#消息队列" class="headerlink" title="消息队列"></a>消息队列</h3></li>
<li><p>如何保证消息的可靠性</p>
</li>
<li><p>消息队列可靠性和最终一致性</p>
</li>
<li><p>消息队列如何防重复</p>
</li>
<li><p>rocketmq 事物机制，和持久化</p>
</li>
<li><p>什么是死信队列</p>
</li>
</ol>
<h3 id="分布式"><a href="#分布式" class="headerlink" title="分布式"></a>分布式</h3><ol>
<li><p>springCloud 常用组件</p>
</li>
<li><p>注册中心怎么保证自己高可用<br>要点：2pc选举过程，崩溃恢复，数据同步过程,两阶段提交（2PC），三阶段提交（3PC）以及它们的相关应用。</p>
</li>
<li><p>分布式系统如何保证数据一致性</p>
</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">InterceptorConfig</span> <span class="keyword">extends</span> <span class="title">WebMvcConfigurerAdapter</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> LoginContextInterceptor loginContextInterceptor;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> SecurityCheckInterceptor securityCheckInterceptor;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> PermissionCheckInterceptor permissionCheckInterceptor;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">addInterceptors</span><span class="params">(InterceptorRegistry registry)</span> </span>&#123;</span><br><span class="line">        registry.addInterceptor(loginContextInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        registry.addInterceptor(securityCheckInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        registry.addInterceptor(permissionCheckInterceptor).addPathPatterns(<span class="string">"/**"</span>);</span><br><span class="line">        <span class="keyword">super</span>.addInterceptors(registry);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">拦截器实现 HandlerInterceptor</span><br><span class="line">HandlerExecutionChain 中会遍历所有的注册的拦截器</span><br></pre></td></tr></table></figure>
<h4 id="访问者模式（visitor）"><a href="#访问者模式（visitor）" class="headerlink" title="访问者模式（visitor）"></a>访问者模式（visitor）</h4><h3 id="linux"><a href="#linux" class="headerlink" title="linux"></a>linux</h3><ol>
<li>linux如何查看负载均衡<br>1）top命令<br>2）uptime 命令<br>3）cat /cat/proc/loadavg</li>
</ol>
<h3 id="操作系统"><a href="#操作系统" class="headerlink" title="操作系统"></a>操作系统</h3><ol>
<li>操作系统的页式存储</li>
</ol>
<h3 id="网络"><a href="#网络" class="headerlink" title="网络"></a>网络</h3><ol>
<li><p>http和https区别</p>
</li>
<li><p>http请求过程和原理</p>
</li>
<li><p>tcp连接的特点</p>
</li>
<li><p>tcp如何保证安全可靠</p>
</li>
<li><p>tcp为什么要三次握手</p>
</li>
<li><p>top的流量控制和拥堵控制</p>
</li>
<li><p>tcp/ip 五层协议是哪些，作用是什么</p>
</li>
<li><p>什么是TCP粘包？怎么解决这个问题</p>
</li>
<li><p>tcp心跳包，为什么不用keepAlive</p>
</li>
<li><p>TCP和UDP的区别<br>TCP是基于连接的，UDP是基于无连接的。 TCP是可靠的，保证数据的顺序和正确性，UDP不可靠，不保证数据的顺序和正确性。 TCP比UDP对系统资源要求更多</p>
</li>
</ol>
<h3 id="设计"><a href="#设计" class="headerlink" title="设计"></a>设计</h3><ol>
<li><p>从千万到亿的数据，会面临哪些问题，解决思路是什么</p>
</li>
<li><p>如何设计存储海量数据的存储系统</p>
</li>
<li><p>如果需要扩展某个功能，如何降低系统耦合度</p>
</li>
<li><p>如果针对某个功能进行优化，你会怎么设计和优化</p>
</li>
</ol>
<h3 id="学习能力"><a href="#学习能力" class="headerlink" title="学习能力"></a>学习能力</h3><ol>
<li><p>最近学的新技术</p>
</li>
<li><p>遇到的最大困难是什么，怎么解决的</p>
</li>
<li><p>读过什么书</p>
</li>
<li><p>平时开发遇到哪些技术问题，怎么解决</p>
</li>
</ol>
<h3 id="项目"><a href="#项目" class="headerlink" title="项目"></a>项目</h3><p>主要有哪些模块</p>
<h3 id="算法"><a href="#算法" class="headerlink" title="算法"></a>算法</h3><ol>
<li>二分搜索过程</li>
<li>快排时间复杂度（<strong>重要</strong>）</li>
<li>冒泡排序，快排，归并排序优缺点及优化</li>
<li>设计一个算法，实现两10g大文件在10m内存中，将两个大文件中重复的放进第三个文件</li>
<li>插入排序，选择排序</li>
<li>b+树</li>
<li>红黑树</li>
<li>二叉搜索树<br>前序遍历，中序遍历，后续遍历，是指父节点在前后中，中序遍历数据是有序的，复杂度等于树高log(n)</li>
</ol>
<p>b树 ，b+树</p>
<pre><code>二叉查找树，红黑树，B-Tree, B+Tree 的区别: 
二叉查找树:二叉搜索树，优点查找快，但是在某些情况下会退化成链表，它是所有
高效查找树的基础，如果不懂这个其他的也学不懂。根本性的东西，最好能自己手写出来。
红黑树:内存查找高效树，不适合大数据量也不适合磁盘存储的。具体的分析就是IO浪费以及读取资源浪费，还有
就是树的深度会很大。适合一些底层系统做内存运算
B- Tree:可以认为是B+Tree过度。只需要知道BTree就可以
B+Tree:最适合大数据的磁盘索引，经典的MySql,所有的数据都存在叶子节点。其他都是索引，增加了系统的稳定
性以及遍历以及查找效率
不同:关键字和Key值。数据存储的地方，双向链表。
M阶:这个由磁盘的页面大小决定，磁盘快和页内存都是4KB.我们的节点数也就是我们的M值应该要尽可能的跟他一
样。这样的好处就是为了我们一次刚好能全部拿出一个节点里面存的所有的数据。</code></pre><h3 id="docker"><a href="#docker" class="headerlink" title="docker"></a>docker</h3><ol>
<li>对docker、k8s的了解</li>
</ol>
<h3 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h3><ol>
<li>主从选举</li>
</ol>
<h3 id="注解"><a href="#注解" class="headerlink" title="注解"></a>注解</h3><p>元数据 注解的注解：Target，Retention<br>ElementType 包括 TYPE，FIELD，METHOD，PARAMETER，CONSTRUCTOR，<br>RetentionPolicy 包括<br> SOURCE，只保留在源码，如override<br> CLASS，保留到class,加载class时候被抛弃<br> RUNTIME 类加载后还会存在<br>2. 去重策略<br>布伦过滤器</p>
<p>docker 设置超级权限<br>docker run -d –name=”centos7” –privileged=true centos:7 /usr/sbin/init</p>
<p>jmap -heap pid 无法使用<br><a href="https://www.jianshu.com/p/0e5d8db8ed5e" target="_blank" rel="noopener">https://www.jianshu.com/p/0e5d8db8ed5e</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/08/01/%E9%9D%A2%E8%AF%95%E5%85%A8%E9%9B%86/" data-id="ckgtnonp60011m8ul9gnl9w6u" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-需要了解" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/31/%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3/" class="article-date">
  <time datetime="2020-07-30T17:22:56.761Z" itemprop="datePublished">2020-07-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/07/31/%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3/">需要了解</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>jvm内存模型<br><a href="https://www.jianshu.com/p/76959115d486" target="_blank" rel="noopener">https://www.jianshu.com/p/76959115d486</a></p>
<p>程序计数器<br>运行时方法区<br>堆</p>
<p>ThreadLocal原理<br><a href="https://www.cnblogs.com/luxiaoxun/p/8744826.html" target="_blank" rel="noopener">https://www.cnblogs.com/luxiaoxun/p/8744826.html</a><br>threadLocalMap用了开放地址法来解决hash冲突<br>hashmap使用链表法</p>
<p>ThreadLocal作用<br>SimpleDataFormater 线程不安全</p>
<p>ThreadLocal创建一个本地线程的SimpleDataFormater</p>
<p>simpleDataFormat为什么线程不安全<br>线程之间共享了Calendar</p>
<p>如何中断一个线程<br>interrupt方法本质上不会进行线程的终止操作的，它不过是改变了线程的中断状态。而改变了此状态带来的影响是，部分可中断阻塞线程方法（比如Object.wait, Thread.sleep，Thread.join）会定期执行isInterrupted方法，检测到此变化，随后会停止阻塞并抛出InterruptedException异常。</p>
<p>一文理解为什么InnoDB选择B+树做索引<br><a href="https://blog.csdn.net/songguangfan/article/details/102475002" target="_blank" rel="noopener">https://blog.csdn.net/songguangfan/article/details/102475002</a></p>
<p>io模型</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/31/%E9%9C%80%E8%A6%81%E4%BA%86%E8%A7%A3/" data-id="ckgtnonnc000xm8ul236z4ern" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-java基础" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/28/java%E5%9F%BA%E7%A1%80/" class="article-date">
  <time datetime="2020-07-28T15:05:11.881Z" itemprop="datePublished">2020-07-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/07/28/java%E5%9F%BA%E7%A1%80/">java基础</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>hashMap 怎么扩容的</p>
<p>hashmap 1.7 死循环</p>
<figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">当重新调整HashMap大小的时候，确实存在条件竞争，因为如果两个线程都发现HashMap需要重新调整大小了，它们会同时试着调整大小。在调整大小的过程中，存储在链表中的元素的次序会反过来，因为移动到新的bucket位置的时候，HashMap并不会将元素放在链表的尾部，而是放在头部，这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了，那么就死循环了。(多线程的环境下不使用HashMap）</span><br><span class="line">https://www.cnblogs.com/zhuoqingsen/p/8577646.html</span><br></pre></td></tr></table></figure>

<p>线程池原理，线程池各个参数含义</p>
<p>int corePoolSize, int maximumPoolSize, long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue<br> Executors.defaultThreadFactory(), defaultHandler</p>
<p> 拒绝策略有哪些<br> AbortPolicy（默认），丢弃任务，并抛出拒绝执行异常<br> DiscardPolicy ，直接丢弃<br> DiscardOldestPolicy， 丢弃线程中最老的一个任务，加入队列中<br> CallerRunsPolicy，阻塞主线程，直接用主线程执行</p>
<h3 id="线程池执行任务过程"><a href="#线程池执行任务过程" class="headerlink" title="线程池执行任务过程"></a>线程池执行任务过程</h3><p><a href="https://www.cnblogs.com/zhuxiaopijingjing/p/12485084.html" target="_blank" rel="noopener">https://www.cnblogs.com/zhuxiaopijingjing/p/12485084.html</a></p>
<p>###怎么停止一个线程<br>ExecutorService  下有 shutdown(有序关闭，已提交的任务继续执行，不在接受新任务)   shutdownnow（停止执行正在执行的任务，等待的任务也不在执行）</p>
<p>###怎么理解线程安全<br>安全来自于竞争，没有竞争就没有安全问题<br>避免共享数据结构，共享状态<br>1）使用线程本地变量<br>2）使用不可变对象<br>如果共享是不可避免的<br>1）使用互斥锁，<br>2）cas原子操作</p>
<p>ThreadLocal原理</p>
<p>LongAdder 原理<br>LongAdder是AtomicLong的升级版，AtomicLong 主要原理是cas,unseft 类，volital ,通过自旋竞争，消耗资源</p>
<p>LongAdder 主要是通过减少竞争，有一个Cell数组，更新数组中的某一个值，也说通过cas进行更新，sum的时候进行求和</p>
<h2 id="java-spi机制"><a href="#java-spi机制" class="headerlink" title="java spi机制"></a>java spi机制</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">say</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Student</span> <span class="keyword">implements</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"i am student"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Teacher</span> <span class="keyword">implements</span> <span class="title">Person</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">say</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.println(<span class="string">"i am teacher"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ServiceLoader&lt;Person&gt; load = ServiceLoader.load(Person<span class="class">.<span class="keyword">class</span>)</span>;</span><br><span class="line">        <span class="keyword">for</span> (Person person : load) &#123;</span><br><span class="line">            person.say();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//META-INF/services下配置文件com.yanglf.spi.Person</span></span><br><span class="line">com.yanglf.spi.Student;</span><br><span class="line">com.yanglf.spi.Teacher;</span><br></pre></td></tr></table></figure>

<p>spi原理<br>ServiceLoader 通过接口名称找到文件路径,按行读取所有的实现类地址, 通过Class.forName加载类,newInstance() 实例化</p>
<p>缺点,会创建配置的所有实现,不能自定义实现类</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/28/java%E5%9F%BA%E7%A1%80/" data-id="ckgtnonmv000am8ul9tjv400b" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-面试准备" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/20/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87/" class="article-date">
  <time datetime="2020-07-19T16:38:16.876Z" itemprop="datePublished">2020-07-20</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/07/20/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87/">面试准备</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="redis"><a href="#redis" class="headerlink" title="redis"></a>redis</h2><h3 id="redis特点"><a href="#redis特点" class="headerlink" title="redis特点"></a>redis特点</h3><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">开源的，基于内存的，key-value型的数据库</span><br></pre></td></tr></table></figure>
<h3 id="redis为什么快"><a href="#redis为什么快" class="headerlink" title="redis为什么快"></a>redis为什么快</h3><figure class="highlight shell"><figcaption><span>script</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">数据在内存中</span><br><span class="line">worker线程为单线程，避免了上下文切换</span><br><span class="line">使用了io多路复用</span><br></pre></td></tr></table></figure>



<p>中间件</p>
<p>hsf服务<br>消息队列metaq<br>redis,redis集群,分布式锁</p>
<p>分库分表<br>英语口语 面试<br>简历</p>
<p>redis</p>
<p>基本数据结构<br>String<br>list，不唯一有序<br>set 唯一，无序<br>sorted set，唯一，排序<br>hash 存储对象</p>
<p>1,Redis 持久化机制</p>
<p>有两种机制，一种是rdb（redis database）,一种是aof（apend only file）<br>rdb机制 有三种方式触发，save,bgsave,自动触发<br>    save命令 redis服务线程阻塞，将内存数据以二进制的方式保存到硬盘上，<br>    bgsave命令 redis 开启一个子线程，fork主线程数据，这时也会阻塞，但是由于在内存中完成，所有速度比较快，fork完成后主线程恢复，子线程将数据同步到硬盘上。如果有备份文件，将新文件替换备份文件<br>    自动触发 save 900 1,300 10,60 10000, 表示多少秒内变动数据多少次 自动触发bgsave<br>aof机制 类似mysql binlog ，每次收到一个写命令都会将命令会将追加的appendonly.aof文件中,aof也有三种触发，always 总是，everysec 每秒，no</p>
<p>rdb 和 aof对比</p>
<p>rdb文件小，系统默认，qps高，恢复速度快，二进制数据文件<br>aof文件大，qps低，恢复速度慢，保存所有写命令的文件<br>rbd容易数据丢失，aof不易丢失</p>
<p>2,缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题</p>
<p>缓存雪崩：大量的key同时过期，导致大量的请求打到数据库上<br>缓存击穿：特定的值进行查询，这时缓存正好过期，导致大量请求落到数据库上（热点数据永不过期，或者对从数据库查询数据加锁）<br>解决方案：从缓存中没有拿到，加锁，从数据库那数据，更新到缓存中，释放锁 ，其他请求拿不到锁，就休眠一段时间，重新调用查询数据接口</p>
<p>缓存穿透：请求不存在的数据，缓存中没有，去查数据库  （缓存中存null值，设置过期时间，不能太长，也不能太短）</p>
<p>即redis的缓存每命中一次,就给命中的缓存增加一定ttl(过期时间)(根据具体情况来设定, 比如10分钟).</p>
<p>一段时间后, 热数据的ttl都会较大, 不会自动失效, 而冷数据基本上过了设定的ttl就马上失效了。</p>
<p>3,热点数据和冷数据是什么</p>
<p>4,Memcache与Redis的区别都有哪些？</p>
<p>一，redis支持数据备份memcache不支持<br>二，value值大小不同，memcache最多1m，redis 512m<br>三，数据类型不同，memcache只有字符串，redis有字符串，list,set，zset,hash等多种类型<br>四，redis比较快，memcache慢</p>
<p>5,单线程的redis为什么这么快<br>6,redis的数据类型，以及每种数据类型的使用场景，Redis 内部结构<br>7,redis的过期策略以及内存淘汰机制【～】<br>定时删除+淘汰删除，没间隔一段时间，随机扫描一些key，有过期key则，删除，get key时，检查key有没有过期，过期删除<br>加入，定期删除没有扫描到，一段时间也没访问，导致key无法被删除， 需要使用内存淘汰策略</p>
<p>volatile-lru：从已设置过期时间的数据集（server.db[i].expires）中挑选最近最少使用的数据淘汰<br>volatile-ttl：从已设置过期时间的数据集（server.db[i].expires）中挑选将要过期的数据淘汰<br>volatile-random：从已设置过期时间的数据集（server.db[i].expires）中任意选择数据淘汰<br>allkeys-lru：从数据集（server.db[i].dict）中挑选最近最少使用的数据淘汰<br>allkeys-random：从数据集（server.db[i].dict）中任意选择数据淘汰<br>no-enviction（驱逐）：禁止驱逐数据，新写入操作会报错<br>volatile-lfu：从已设置过期时间的数据集挑选使用频率最低的数据淘汰。<br>allkeys-lfu：从数据集中挑选使用频率最低的数据淘汰</p>
<p>8,Redis 为什么是单线程的，优点<br>9,如何解决redis的并发竞争key问题<br>10,Redis 集群方案应该怎么做？都有哪些方案？</p>
<p>1，主从模式<br>2，cluster集群模式 16384个槽<br>3,codis集群方案</p>
<p>11,有没有尝试进行多机redis 的部署？如何保证数据一致的？<br>12,对于大量的请求怎么样处理<br>1 缓存预热<br>2 设置过期时间+随机数<br>3 数据散列开</p>
<p>14,讲解下Redis线程模型</p>
<p>15,为什么Redis的操作是原子性的，怎么保证原子性的？<br>16,Redis事务<br>17,Redis实现分布式锁<br>18，如何保证redis中都是热点数据<br>答：有一种简单的缓存失效策略，lru，最近少用淘汰，<br>每命中一次缓存，增加一点的过期时间，比如10分钟，热点数据一般过期时间比较大，不会失效，用的少的数据容易失效</p>
<p>19 redis和数据库双写一致性问题<br>采用延时双删策略<br>先删除缓存，再更新数据库，再更新缓存，设置一个比较短的过期时间<br><a href="https://blog.csdn.net/qq_37779352/article/details/82977921" target="_blank" rel="noopener">https://blog.csdn.net/qq_37779352/article/details/82977921</a></p>
<p>20 redis 怎么实现分布式锁</p>
<p>set key value nx px 3000</p>
<p>23 redis 是单线程还是多线程</p>
<p>一般说redis是单线程，因为文件事件分派器队列的消费是单线程的<br>多线程的方式在后台删除对象</p>
<p>redis6.0上了多线程是指，在网络Io处理上用了多线程，入网络读写，协议解析</p>
<p>布隆过滤器（推荐）解决缓存穿透<br>bit数组，起始值为0，对key进行多个hash算法求值，比如得到10,20,30，这时这个数组的这三个下标的值就为1 ，</p>
<p>一致性hash算法<br>将1 2-31 个数分布到一个hash环上，对redis服务器ip或主机名取hash，确定在环上文字，<br>然后对key取hash，也能确定在环上位置，顺时针走，遇到的第一台服务器就是需要存放的服务器，<br>增加和删除服务器，只会影响一台服务器</p>
<p>hash环数据倾斜问题，可以通过增加虚拟节点解决，节点越多，数据分布越均匀</p>
<p><a href="https://blog.csdn.net/Butterfly_resting/article/details/89668661" target="_blank" rel="noopener">https://blog.csdn.net/Butterfly_resting/article/details/89668661</a></p>
<p>es倒排索引</p>
<p>微服务好处与缺点</p>
<p>优点<br>1）独立可扩展<br>2)独立服务升级<br>3）易维护<br>4）语言无关<br>5）故障隔离 比如内存泄漏，数据库连接未关闭<br>6）与docker方便集成</p>
<p>缺点<br>服务带来的延迟问题</p>
<p>mq重复消费的问题</p>
<p>reentrantLock 和 synchronized 区别</p>
<p><a href="https://blog.csdn.net/qq_40551367/article/details/89414446" target="_blank" rel="noopener">https://blog.csdn.net/qq_40551367/article/details/89414446</a></p>
<p>（1）什么是 CPU 缓存行？<br>缓存是由缓存行组成的，通常是 64 字节（常用处理器的缓存行是 64 字节的，比较旧的处理器缓存行是 32 字节），并且它有效地引用主内存中的一块地址。</p>
<p>一个 Java 的 long 类型是 8 字节，因此在一个缓存行中可以存 8 个 long 类型的变量。<br>（2）什么是内存屏障？</p>
<p>（3）什么是伪共享？<br>当多线程修改互相独立的变量时，如果这些变量共享同一个缓存行，就会无意中影响彼此的性能，这就是伪共享。<br><a href="https://www.cnblogs.com/tong-yuan/p/FalseSharing.html" target="_blank" rel="noopener">https://www.cnblogs.com/tong-yuan/p/FalseSharing.html</a></p>
<p>（4）如何避免伪共享？</p>
<p>@ Contended </p>
<p>Thread.join<br> 调用方线程（调用join方法的线程）执行等待操作，直到被调用的线程（join方法所属的线程）结束，再被唤醒<br><a href="https://www.jianshu.com/p/367fa66bf3f2" target="_blank" rel="noopener">https://www.jianshu.com/p/367fa66bf3f2</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/20/%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87/" data-id="ckgtnonnd000ym8ulfmmc1vhf" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-双亲委派" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/19/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/" class="article-date">
  <time datetime="2020-07-18T16:41:51.518Z" itemprop="datePublished">2020-07-19</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/07/19/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/">双亲委派</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <pre><code>先有AppClassLoader加载 
appClassLoader交给 父类ExtClassLoader加载
extClassLoader 没有父类，交给bootStrapClassLoader
bootStrapClassLoader尝试加载，因为bootStrapClassLoader只会加载核心类库（rt.jar,resource.jar,Charset.jar）,所以就会找不到类，包ClassNotFindException,
这个异常被catch掉，在extClassLoader中被加载的类就是空，extClassLoader尝试自己加载类，extClassLoader只会加载lib下ext文件中的jar包，所以找不到类，
同样报异常，回到AppClassLoader,然后appClassLoader尝试加载类，appClassLoader可以加载用户自定义的类，能加载到类，
加载类过程调用findClass(),defindClass


双亲委派模型好处，
1，避免类被重复加载，同一个类加载器并且类全路径相同，类才相同
2，保证java核心api不被篡改，比如自定义一个java.lang.Object，</code></pre>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/19/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/" data-id="ckgtnonn9000rm8ulh4c6a4nv" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-zookeeper" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/07/06/zookeeper/" class="article-date">
  <time datetime="2020-07-05T16:21:50.282Z" itemprop="datePublished">2020-07-06</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/07/06/zookeeper/">zookeeper</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>查看zookeeper启动日志<br> ./zkServer.sh start-foreground</p>
<p>查看当前节点状态<br>./zkServer.sh status</p>
<p>创建一个临时节点<br>create -e /person yang</p>
<p>创建一个持久顺序节点</p>
<p>create -s /person yang</p>
<p>ZooKeeper 是一个典型的分布式数据一致性解决方案，分布式应用程序可以基于<br>ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。</p>
<ol>
<li>zookeeper四种节点<br>持久化节点<br>持久化顺序节点<br>临时节点 临时节点在客户端会话结束后，就会自动删除<br>临时顺序节点 </li>
</ol>
<ol start="2">
<li><p>zookeeper应用场景<br>1、命名服务<br>2、配置管理<br>3、集群管理<br>4、分布式锁<br>5、队列管理</p>
</li>
<li><p>zookeeper如何选举leader</p>
</li>
<li><p>zookeeper为什么需要leader </p>
</li>
<li><p>zk原子广播机制原理<br>数据一致性的算法，即ZAB（ZooKeeper Atomic Broadcast ）</p>
</li>
</ol>
<p>消息机制保障：可靠传送（如果消息m被一台服务器送达，它最终会被送达到所有服务器），<br>顺序</p>
<p>Zookeeper的核心是原子广播，这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式，它们分别是恢复模式和广播模式。</p>
<p>　　　当服务启动或者在领导者崩溃后，Zab就进入了恢复模式，当领导者被选举出来，且大多数server的完成了和leader的状态同步以后，恢复模式就结束了。</p>
<p>　　　状态同步保证了leader和server具有相同的系统状态</p>
<p>　　» 一旦leader已经和多数的follower进行了状态同步后，他就可以开始广播消息了，即进入广播状态。这时候当一个server加入zookeeper服务中，它会在恢复模式下启动，</p>
<p>　　　发现leader，并和leader进行状态同步。待到同步结束，它也参与消息广播。Zookeeper服务一直维持在Broadcast状态，直到leader崩溃了或者leader失去了大部分</p>
<p>　　　的followers支持。</p>
<p>　　» 广播模式需要保证proposal被按顺序处理，因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。</p>
<p>　　　实现中zxid是一个64为的数字，它高32位是epoch用来标识leader关系是否改变，每次一个leader被选出来，它都会有一个新的epoch。低32位是个递增计数。</p>
<p>　　» 当leader崩溃或者leader失去大多数的follower，这时候zk进入恢复模式，恢复模式需要重新选举出一个新的leader，让所有的server都恢复到一个正确的状态。　</p>
<p>　　» 每个Server启动以后都询问其它的Server它要投票给谁。<br>　　» 对于其他server的询问，server每次根据自己的状态都回复自己推荐的leader的id和上一次处理事务的zxid（系统启动时每个server都会推荐自己）<br>　　» 收到所有Server回复以后，就计算出zxid最大的哪个Server，并将这个Server相关信息设置成下一次要投票的Server。<br>　　» 计算这过程中获得票数最多的的sever为获胜者，如果获胜者的票数超过半数，则改server被选为leader。否则，继续这个过程，直到leader被选举出来　　</p>
<p>　　» leader就会开始等待server连接<br>　　» Follower连接leader，将最大的zxid发送给leader<br>　　» Leader根据follower的zxid确定同步点<br>　　» 完成同步后通知follower 已经成为uptodate状态<br>　　» Follower收到uptodate消息后，又可以重新接受client的请求进行服务了</p>
<ol start="6">
<li><p>zk内存数据库</p>
</li>
<li><p>zk节点（node） 本身携带数据</p>
</li>
<li><p>zk怎么保证数据强一致性<br>据说Paxos算法的难理解与算法的知名度一样令人敬仰，所以我们先看如何保持数据的一致性，这里有个原则就是：<br>　　• 在一个分布式数据库系统中，如果各节点的初始状态一致，每个节点都执行相同的操作序列，那么他们最后能得到一个一致的状态。<br>　　• Paxos算法解决的什么问题呢，解决的就是保证每个节点执行相同的操作序列。好吧，这还不简单，master维护一个<br>　　   全局写队列，所有写操作都必须 放入这个队列编号，那么无论我们写多少个节点，只要写操作是按编号来的，就能保证一<br>　　　致性。没错，就是这样，可是如果master挂了呢。<br>　　• Paxos算法通过投票来对写操作进行全局编号，同一时刻，只有一个写操作被批准，同时并发的写操作要去争取选票，<br>　　　只有获得过半数选票的写操作才会被 批准（所以永远只会有一个写操作得到批准），其他的写操作竞争失败只好再发起一<br>　　　轮投票，就这样，在日复一日年复一年的投票中，所有写操作都被严格编号排 序。编号严格递增，当一个节点接受了一个<br>　　　编号为100的写操作，之后又接受到编号为99的写操作（因为网络延迟等很多不可预见原因），它马上能意识到自己 数据<br>　　　不一致了，自动停止对外服务并重启同步过程。任何一个节点挂掉都不会影响整个集群的数据一致性（总2n+1台，除非挂掉大于n台）。<br>　 总结<br>　　• Zookeeper 作为 Hadoop 项目中的一个子项目，是 Hadoop 集群管理的一个必不可少的模块，它主要用来控制集群中的数据，</p>
</li>
</ol>
<p>　　　如它管理 Hadoop 集群中的 NameNode，还有 Hbase 中 Master Election、Server 之间状态同步等<br>Paxos(派克寿司)算法就是用来解决这类问题，多台服务器通过内部投票表决机制决定一个数据的更新与写入</p>
<ol start="9">
<li><p>一致性级别划分<br>强一致性<br>顺序一致性<br>弱一致性（最终一致性）</p>
</li>
<li><p>cap原理<br>c一致性<br>a可用性<br>p分区容错性<br>节点多了会导致写数据延时变大，因为更多的节点需要同步<br>节点多了Leader选举耗时变长，从而会放大网络的问题， 可以通过引入 observer（不参与选举）节点缓解这个问题.</p>
</li>
</ol>
<p>base理论<br>ba基本可用<br>s 柔韧性<br>e 最终一致性<br>原子性和持久性必须从根本上保障，为了可用性、性能和服务降级的需要，只有降低一致性和隔离性的要求。</p>
<ol start="11">
<li><p>zk数据模型</p>
</li>
<li><p>层次化的目录结构</p>
</li>
<li><p>唯一路径表示</p>
</li>
<li><p>节点包含数据和子节点，临时数据不包含子节点</p>
</li>
<li><p>数据解读</p>
</li>
</ol>
<p>cZxid = 0x89  创建的事物ID<br>ctime = Mon Aug 10 00:26:27 CST 2020 创建时间<br>mZxid = 0x89 修改的事物ID<br>mtime = Mon Aug 10 00:26:27 CST 2020 修改时间<br>pZxid = 0x89 该节点的子节点列表最后一次修改时的事务id，只有子节点列表变更才会更新pZxid，子节点内容变更不会更新<br>cversion = 0 子节点版本号，当前节点的子节点每次变化时值增加1<br>dataVersion = 0 数据节点内容版本号，节点创建时为0，每更新一次节点内容(不管内容有无变化)该版本号的值增加1<br>aclVersion = 0 节点的ACL版本号，表示该节点ACL信息变更次数<br>ephemeralOwner = 0x100de2956c70006  创建该临时节点的会话的sessionId；如果当前节点为持久节点，则ephemeralOwner=0<br>dataLength = 2 数据节点内容长度<br>numChildren = 0 当前节点的子节点个数</p>
<p>13.为什么zookeeper集群的数目，一般为奇数个</p>
<p>•Leader选举算法采用了Paxos协议；<br>Paxos核心思想：当多数Server写成功，则任务数据写成功如果有3个Server，则两个写成功即可；如果有4或5个Server，则三个写成功即可。<br>Server数目一般为奇数（3、5、7）如果有3个Server，则最多允许1个Server挂掉；如果有4个Server，则同样最多允许1个Server挂掉由此，</p>
<p>我们看出3台服务器和4台服务器的的容灾能力是一样的，所以为了节省服务器资源，一般我们采用奇数个数，作为服务器部署个数。</p>
<ol start="14">
<li>Observer　　</li>
</ol>
<p>　　• Zookeeper需保证高可用和强一致性；<br>　　• 为了支持更多的客户端，需要增加更多Server；<br>　　• Server增多，投票阶段延迟增大，影响性能；<br>　　• 权衡伸缩性和高吞吐率，引入Observer<br>　　• Observer不参与投票；<br>　　• Observers接受客户端的连接，并将写请求转发给leader节点；<br>　　• 加入更多Observer节点，提高伸缩性，同时不影响吞吐率</p>
<ol start="15">
<li>分布式锁<br>访问的时候会创建带顺序号的临时/短暂(EPHEMERAL_SEQUENTIAL)节点，<br>比如，系统A创建了id_000000节点，系统B创建了id_000002节点，系统C创建了id_000001节点。<br>接着，拿到/locks节点下的所有子节点(id_000000,id_000001,id_000002)，判断自己创建的是不是最小的那个节点</li>
</ol>
<p>如果是，则拿到锁。</p>
<p>释放锁：执行完操作后，把创建的节点给删掉</p>
<p>如果不是，则监听比自己要小1的节点变化<br>原理：</p>
<p>系统A拿到/locks节点下的所有子节点，经过比较，发现自己(id_000000)，是所有子节点最小的。所以得到锁</p>
<p>系统B拿到/locks节点下的所有子节点，经过比较，发现自己(id_000002)，不是所有子节点最小的。所以监听比自己小1的节点id_000001的状态</p>
<p>系统C拿到/locks节点下的所有子节点，经过比较，发现自己(id_000001)，不是所有子节点最小的。所以监听比自己小1的节点id_000000的状态……等到系统A执行完操作以后，将自己创建的节点删除(id_000000)。通过监听，系统C发现id_000000节点已经删除了，发现自己已经是最小的节点了，于是顺利拿到锁….</p>
<ol start="16">
<li>ZooKeeper的ZAB算法与Paxos的本质区别</li>
</ol>
<p>Zab 协议分为三大块：</p>
<ul>
<li>广播（boardcast）：Zab 协议中，所有的写请求都由 leader 来处理。正常工作状态下，leader 接收请求并通过广播协议来处理。</li>
<li>恢复（recovery）：当服务初次启动，或者 leader 节点挂了，系统就会进入恢复模式，直到选出了有合法数量 follower 的新 leader，<br>然后新 leader 负责将整个系统同步到最新状态。</li>
<li>选举（Election）：Zab通过消息版本号选举出Leader来负责所在区域的写入工作<br>选举：<br>成为 leader 的条件<br>选epoch最大的<br>epoch相等，选 zxid 最大的<br>epoch和zxid都相等，选择server id最大的（就是我们配置data目录下的myid）<br>节点在选举开始都默认投票给自己，当接收其他节点的选票时，会根据上面的条件更改自己的选票并重新发送选票给其他节点，当有一个节点的得票超过半数，<br>该节点会设置自己的状态为 leading，其他节点会设置自己的状态为 following。<br>恢复：<br>这一阶段 follower 发送它们的 lastZixd 给 leader，leader 根据 lastZixd 决定如何同步数据。这里的实现跟前面 Phase 2 有所不同：<br>Follower 收到 TRUNC 指令会中止 L.lastCommittedZxid 之后的提议，收到 DIFF 指令会接收新的提议。<br>广播：<br>广播的过程实际上是一个简化的二阶段提交过程：</li>
</ul>
<ol>
<li>Leader 接收到消息请求后，将消息赋予一个全局唯一的 64 位自增 id，叫做：zxid，通过 zxid 的大小比较即可实现因果有序这一特性。</li>
<li>Leader 通过先进先出队列（通过 TCP 协议来实现，以此实现了全局有序这一特性）将带有 zxid 的消息作为一个提案（proposal）分发给所有 follower。</li>
<li>当 follower 接收到 proposal，先将 proposal 写到硬盘，写硬盘成功后再向 leader 回一个 ACK。</li>
<li>当 leader 接收到合法数量的 ACKs 后，leader 就向所有 follower 发送 COMMIT 命令，同事会在本地执行该消息。</li>
<li>当 follower 收到消息的 COMMIT 命令时，就会执行该消息</li>
</ol>
<p>什么是脑裂</p>
<p>zookeeper集群中存在多个leader</p>
<p>zab协议怎么解决脑裂<br>选举leader要求支持过半,也叫快速选举法,不需要等所有的flower进行投票选举</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/07/06/zookeeper/" data-id="ckgtnonol000zm8ul2p1zemkz" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-gradle知识" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/06/12/gradle%E7%9F%A5%E8%AF%86/" class="article-date">
  <time datetime="2020-06-11T17:14:46.867Z" itemprop="datePublished">2020-06-12</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/06/12/gradle%E7%9F%A5%E8%AF%86/">gradle知识</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <ul>
<li><p>配置阿里镜像<br>在build.gradle中</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">repositories &#123;</span><br><span class="line">    maven &#123; url <span class="string">'http://maven.aliyun.com/nexus/content/groups/public/'</span> &#125;</span><br><span class="line">    mavenCentral()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>Java之idea创建gradle项目默认没有src和resources解决方法</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">task <span class="string">"create-dirs"</span> &lt;&lt; &#123;</span><br><span class="line">    sourceSets*.java.srcDirs*.each&#123;</span><br><span class="line">        it.mkdirs()</span><br><span class="line">    &#125;</span><br><span class="line">    sourceSets*.resources.srcDirs*.each&#123;</span><br><span class="line">        it.mkdirs()</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/06/12/gradle%E7%9F%A5%E8%AF%86/" data-id="ckgtnonms0005m8ul3901b5ew" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  
    <article id="post-内部穿透" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2020/05/31/%E5%86%85%E9%83%A8%E7%A9%BF%E9%80%8F/" class="article-date">
  <time datetime="2020-05-31T11:23:33.390Z" itemprop="datePublished">2020-05-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/blog/2020/05/31/%E5%86%85%E9%83%A8%E7%A9%BF%E9%80%8F/">内部穿透</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -jar holer-server-1.2.jar</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yanglf007.gitee.io/blog/2020/05/31/%E5%86%85%E9%83%A8%E7%A9%BF%E9%80%8F/" data-id="ckgtnonn9000qm8ul814var3b" class="article-share-link">Share</a>
      
      
    </footer>
  </div>
  
</article>


  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/blog/page/2/">&amp;laquo; Prev</a><a class="page-number" href="/blog/">1</a><a class="page-number" href="/blog/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/blog/page/4/">4</a><a class="extend next" rel="next" href="/blog/page/4/">Next &amp;raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archives</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/10/">October 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/08/">August 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/07/">July 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/06/">June 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/05/">May 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2020/04/">April 2020</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Recent Posts</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/blog/2020/10/25/%E6%AF%8F%E6%97%A5%E5%AD%A6%E4%B9%A0/">每日学习</a>
          </li>
        
          <li>
            <a href="/blog/2020/10/12/mybatis-plus/">mybatis-plus</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/30/%E7%A7%92%E6%9D%80%E7%B3%BB%E7%BB%9F/">秒杀系统</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/29/elasticsearch%E7%9F%A5%E8%AF%86/">elasticsearch知识</a>
          </li>
        
          <li>
            <a href="/blog/2020/08/28/redis%E9%9D%A2%E8%AF%95/">redis面试</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2020 yanglf007<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/blog/" class="mobile-nav-link">Home</a>
  
    <a href="/blog/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/blog/fancybox/jquery.fancybox.css">

  
<script src="/blog/fancybox/jquery.fancybox.pack.js"></script>




<script src="/blog/js/script.js"></script>




  </div>
</body>
</html>